//! @file   lc_atomic_word.cpp
//! @brief  
//! @author Sayan Chaliha
//! @date   September, 2011
//!
//! 
#include <lc_atomic_word.h>

namespace cyan {
  AtomicWord::AtomicWord() : data_(0) {
  }

  AtomicWord::AtomicWord(Int32 value) : data_(value) {
  }

  AtomicWord::~AtomicWord() {
  }

  Int32 AtomicWord::atomicFetchAndAdd(Int32 value) {
#ifdef LC_GNU_ATOMIC_BUILTINS
    return __gnu_cxx::__exchange_and_add(&this->data_, value);
#elif defined (LC_MSVC_ATOMIC_BUILTINS)
    // MSVC Interlocked function call
#elif !defined (LC_ATOMIC_BUILTINS)
    Int32 returnValue = this->data_;
    this->data_ += value;
    return returnValue;
#endif /* LC_GNU_ATOMIC_BUILTINS */
  }

  void AtomicWord::increment() {
#ifndef LC_ATOMIC_BUILTINS
    WriteGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    this->atomicFetchAndAdd(1);
  }

  void AtomicWord::decrement() {
#ifndef LC_ATOMIC_BUILTINS
    WriteGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    this->atomicFetchAndAdd(-1);
  }

  void AtomicWord::add(Int32 value) {
#ifndef LC_ATOMIC_BUILTINS
    WriteGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    this->atomicFetchAndAdd(value);
  }

  void AtomicWord::set(Int32 value) {
#ifndef LC_ATOMIC_BUILTINS
    WriteGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    this->data_ = value;
  }

  UInt32 AtomicWord::hashCode() const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return static_cast<UInt32>(this->data_);
  }

  AtomicWord& AtomicWord::operator =(Int32 value) {
#ifndef LC_ATOMIC_BUILTINS
    WriteGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    this->data_ = value;
    return const_cast<AtomicWord&>(*this);
  }

  AtomicWord& AtomicWord::operator =(const AtomicWord& value) {
#ifndef LC_ATOMIC_BUILTINS
    WriteGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    if (this != &value)
      this->data_ = value.data_;
    return const_cast<AtomicWord&>(*this);
  }

  AtomicWord& AtomicWord::operator ++() {
#ifndef LC_ATOMIC_BUILTINS
    WriteGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    this->atomicFetchAndAdd(1);
    return const_cast<AtomicWord&>(*this);
  }

  AtomicWord& AtomicWord::operator --() {
#ifndef LC_ATOMIC_BUILTINS
    WriteGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    this->atomicFetchAndAdd(-1);
    return const_cast<AtomicWord&>(*this);
  }

  AtomicWord AtomicWord::operator ++(Int) {
#ifndef LC_ATOMIC_BUILTINS
    WriteGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    Int32 returnValue = this->data_;
    this->atomicFetchAndAdd(1);
    return returnValue;
  }

  AtomicWord AtomicWord::operator --(Int) {
#ifndef LC_ATOMIC_BUILTINS
    WriteGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    Int32 returnValue = this->data_;
    this->atomicFetchAndAdd(-1);
    return returnValue;
  }

  Bool AtomicWord::operator ==(Int32 value) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ == value;
  }

  Bool AtomicWord::operator !=(Int32 value) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ != value;
  }

  Bool AtomicWord::operator <=(Int32 value) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ <= value;
  }

  Bool AtomicWord::operator >=(Int32 value) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ >= value;
  }

  Bool AtomicWord::operator <(Int32 value) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ < value;
  }

  Bool AtomicWord::operator >(Int32 value) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ > value;
  }

  Bool AtomicWord::operator ==(const AtomicWord& atomicWord) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ == atomicWord.data_;
  }

  Bool AtomicWord::operator !=(const AtomicWord& atomicWord) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ != atomicWord.data_;
  }

  Bool AtomicWord::operator <=(const AtomicWord& atomicWord) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ <= atomicWord.data_;
  }

  Bool AtomicWord::operator >=(const AtomicWord& atomicWord) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ >= atomicWord.data_;
  }

  Bool AtomicWord::operator <(const AtomicWord& atomicWord) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ < atomicWord.data_;
  }

  Bool AtomicWord::operator >(const AtomicWord& atomicWord) const {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(this->guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return this->data_ > atomicWord.data_;
  }

  Bool operator ==(Int32 lhs, const AtomicWord& rhs) {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(rhs.guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return lhs == rhs.data_;
  }

  Bool operator !=(Int32 lhs, const AtomicWord& rhs) {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(rhs.guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return lhs != rhs.data_;
  }

  Bool operator <=(Int32 lhs, const AtomicWord& rhs) {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(rhs.guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return lhs <= rhs.data_;
  }

  Bool operator >=(Int32 lhs, const AtomicWord& rhs) {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(rhs.guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return lhs >= rhs.data_;
  }

  Bool operator <(Int32 lhs, const AtomicWord& rhs) {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(rhs.guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return lhs < rhs.data_;
  }

  Bool operator >(Int32 lhs, const AtomicWord& rhs) {
#ifndef LC_ATOMIC_BUILTINS
    ReadGuard guard(rhs.guard_);
#endif /* LC_ATOMIC_BUILTINS */
    return lhs > rhs.data_;
  }
}
